package com.ncmem.up6.store.minio;

import com.ncmem.up6.model.FileInf;
import okhttp3.*;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Iterator;

public class MinioTool {

    /**
     * API：
     * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_PutObject.html
     * @param key 文件名称,QQ.exe
     * @param data
     */
    public static String putObject(String key,byte[] data) {

        MinioConfig cfg = new MinioConfig();
        OkHttpClient c = new OkHttpClient();
        //http://192.168.0.111:9001/test//123.txt
        String url = cfg.endpoint+ "/" +cfg.bucket + "//"+key;
        MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");

        RequestBody body = RequestBody.create(JSON,data);


        MinioAuthorization auth = new MinioAuthorization();
        auth.setConfig(cfg)
                .setMethod("PUT")
                .setData(data)
                .setUrl(url)
                .setContentType("application/octet-stream; charset=utf-8");

        try {
            String authstr = auth.Authorization();

            Request r = new Request.Builder()
                    .url(url)
                    .put(body)
                    .header("Content-Length", String.valueOf(data.length) )
                    //.header("Content-Md5", auth.dataMd5)
                    .header("x-amz-date", auth.getTimeIso())
                    .header("x-amz-content-sha256", auth.data_sha256_Hash)
                    //.header("x-amz-content-sha256", auth.getDataHash())
                    .header("Authorization", authstr)
                    .build();
            Call call = c.newCall(r);
            //同步调用,返回Response,会抛出IO异常
            Response res = call.execute();
            //System.out.println("返回头：\n"+res.headers().toString());
            return res.header("ETag");

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "";
    }

    /**
     * API：
     * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_GetObject.html
     * @param key 以左斜杠开始的资源路径。/guid/QQ.exe径
     * @param blockOffset
     * @param blockLen
     * @return
     */
    public static byte[] getObject(String key,long blockOffset,long blockLen) throws IOException {
        MinioConfig cfg = new MinioConfig();
        OkHttpClient c = new OkHttpClient();
        //http://192.168.0.111:9001/test//123.txt?uploads

        String url = cfg.endpoint+ "/" +cfg.bucket + "/"+key;
        String range = "bytes="+String.valueOf(blockOffset)+"-"+String.valueOf(blockOffset+blockLen-1);

        MinioAuthorization auth = new MinioAuthorization();

        auth.setConfig(cfg)
                .setMethod("GET")
                .setData(("").getBytes())
                .setUrl(url)
                .delHead("content-length")
                .delHead("content-type")
                .delHead("Content-Md5")
                .setContentType("application/octet-stream; charset=utf-8");

        try {
            String authstr = auth.Authorization();

            Request r = new Request.Builder()
                    .url(url)
                    .get()
                    .header("x-amz-date", auth.getTimeIso())
                    .header("x-amz-content-sha256", auth.getDataHash())
                    .header("Range", range)
                    .header("Authorization", authstr)
                    .build();
            Call call = c.newCall(r);
            //同步调用,返回Response,会抛出IO异常
            Response res = call.execute();
            //System.out.println("返回头：\n"+res.headers().toString());

            /**返回值
             *
             HTTP/1.1 206 Partial Content
             x-amz-id-2: MzRISOwyjmnupCzjI1WC06l5TTAzm7/JypPGXLh0OVFGcJaaO3KW/hRAqKOpIEEp
             x-amz-request-id: 47622117804B3E11
             Date: Fri, 28 Jan 2011 21:32:09 GMT
             x-amz-meta-title: the title
             Last-Modified: Fri, 28 Jan 2011 20:10:32 GMT
             ETag: "b2419b1e3fd45d596ee22bdf62aaaa2f"
             Accept-Ranges: bytes
             Content-Range: bytes 0-9/443
             Content-Type: text/plain
             Content-Length: 10
             Server: AmazonS3

             [10 bytes of object data]

             */
            return res.body().bytes();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw  new IOException("minio getObject error");
        }
    }

    /**
     * API：
     * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_CreateMultipartUpload.html
     * @param key guid/QQ.exe，
     * @return
     */
    public static String CreateMultipartUpload(String key) {

        //System.out.println("\n minio.创建分片上传："+key);
        MinioConfig cfg = new MinioConfig();
        OkHttpClient c = new OkHttpClient();
        //http://192.168.0.111:9001/test//123.txt?uploads
        String url = cfg.endpoint+ "/" +cfg.bucket + "/"+key+"?uploads";
        MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");

        RequestBody body = RequestBody.create(JSON,"");

        MinioAuthorization auth = new MinioAuthorization();
        auth.setConfig(cfg)
                .setMethod("POST")
                .setData(("").getBytes())
                .setUrl(url)
                .delHead("Content-Md5")
                .setContentType("application/octet-stream; charset=utf-8");

        try {
            String authstr = auth.Authorization();

            Request r = new Request.Builder()
                    .url(url)
                    .post(body)
                    .header("Content-Length", "0" )
                    //.header("Content-Md5", auth.dataMd5)
                    .header("x-amz-date", auth.getTimeIso())
                    .header("x-amz-content-sha256", auth.data_sha256_Hash)
                    //.header("x-amz-content-sha256", auth.getDataHash())
                    .header("Authorization", authstr)
                    .build();
            Call call = c.newCall(r);
            //同步调用,返回Response,会抛出IO异常
            Response res = call.execute();
            //System.out.println("返回头：\n"+res.headers().toString());

            /**返回值
             * 	<InitiateMultipartUploadResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
             <Bucket>example-bucket</Bucket>
             <Key>example-object</Key>
             <UploadId>VXBsb2FkIElEIGZvciA2aWWpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA</UploadId>
             </InitiateMultipartUploadResult>

             */
            String str = res.body().string();
            //System.out.println("返回值："+str);
            SAXReader reader = new SAXReader();
            //2.加载xml
            Document doc = reader.read(new ByteArrayInputStream(str.getBytes("UTF-8")) );
            Element root = doc.getRootElement();
            Iterator iter = root.elementIterator();
            String uploadId="";
            while(iter.hasNext())
            {
                Element e = (Element)iter.next();
                e.getStringValue();
                if(StringUtils.equals(e.getName(),"UploadId")) uploadId=e.getStringValue();
            }
            return uploadId;

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "";
    }

    /**
     * API:
     * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_UploadPart.html
     * @param key /guid/QQ.exe
     * @param part 基于1
     * @param uploadID
     * @param data
     */
    public static String UploadPart(String key,int part,String uploadID,byte[] data) {
        //System.out.println("\n 上传片："+key +  " partNumber="+String.valueOf(part)+" UploadId="+uploadID);

        MinioConfig cfg = new MinioConfig();
        OkHttpClient c = new OkHttpClient();
        //http://192.168.0.111:9001/test//123.txt
        String url = cfg.endpoint+ "/" +cfg.bucket + "/"+key+"?partNumber="+String.valueOf(part)+"&uploadId="+uploadID;
        //System.out.println("查询字符串：\n"+url);
        MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");
        RequestBody body = RequestBody.create(JSON,data);

        MinioAuthorization auth = new MinioAuthorization();
        auth.setConfig(cfg)
                .setMethod("PUT")
                .setData(data)
                .setUrl(url)
                //.delHead("x-amz-content-sha256")
                .delHead("content-md5")
                .delHead("content-type")
                .setContentType("application/octet-stream; charset=utf-8");

        try {
            String authstr = auth.Authorization();

            Request r = new Request.Builder()
                    .url(url)
                    .put(body)
                    .header("Content-Length", String.valueOf(data.length) )
                    .header("x-amz-date", auth.getTimeIso())
                    .header("x-amz-content-sha256", auth.data_sha256_Hash)
                    .header("Authorization", authstr)
                    .build();
            Call call = c.newCall(r);
            //同步调用,返回Response,会抛出IO异常
            Response res = call.execute();
            //System.out.println("返回内容：\n"+res.body().string());
            //System.out.println("返回头：\n"+res.headers().toString());

            /**
             *
             HTTP/1.1 100 Continue   HTTP/1.1 200 OK
             x-amz-id-2: Zn8bf8aEFQ+kBnGPBc/JaAf9SoWM68QDPS9+SyFwkIZOHUG2BiRLZi5oXw4cOCEt
             x-amz-request-id: 5A37448A37622243
             Date: Wed, 28 May 2014 19:40:12 GMT
             ETag: "7e10e7d25dc4581d89b9285be5f384fd"
             x-amz-server-side-encryption-customer-algorithm: AES256
             x-amz-server-side-encryption-customer-key-MD5: ZjQrne1X/iTcskbY2example
             */
            return res.header("ETag").replaceAll("\"", "");

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 参数：pathSvr,minio_id(UploadId)
     * API:
     * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_CompleteMultipartUpload.html
     * POST /Key+?uploadId=UploadId HTTP/1.1
     Host: Bucket.s3.amazonaws.com
     <?xml version="1.0" encoding="UTF-8"?>
     <CompleteMultipartUpload xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
     <Part>
     <ChecksumCRC32>string</ChecksumCRC32>
     <ChecksumCRC32C>string</ChecksumCRC32C>
     <ChecksumSHA1>string</ChecksumSHA1>
     <ChecksumSHA256>string</ChecksumSHA256>
     <ETag>string</ETag>
     <PartNumber>integer</PartNumber>
     </Part>
     ...
     </CompleteMultipartUpload>

     * @param file
     */
    public static boolean CompleteMultipartUpload(FileInf file)
    {
        //System.out.println("\n minio.合并文件：\n key="+file.S3Key()+"\n UploadId="+file.minio_id);
        MinioConfig cfg = new MinioConfig();
        OkHttpClient c = new OkHttpClient();
        //http://192.168.0.111:9001/test//123.txt
        String url = cfg.endpoint+ "/" +cfg.bucket + "/"+file.S3Key()+"?uploadId="+file.object_id;
        //System.out.println("查询字符串：\n"+url);
        MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");

        String etags=file.etags();
        byte[] data= etags.getBytes();

        RequestBody body = RequestBody.create(JSON,etags);

        MinioAuthorization auth = new MinioAuthorization();
        auth.setConfig(cfg)
                .setMethod("POST")
                .setUrl(url)
                .setData(data)
                .delHead("Content-Md5")
                .delHead("content-type")
                .setContentType("application/octet-stream; charset=utf-8");

        try {
            String authstr = auth.Authorization();

            Request r = new Request.Builder()
                    .url(url)
                    .post(body)
                    .header("Content-Length", String.valueOf(data.length) )
                    .header("x-amz-date", auth.getTimeIso())
                    .header("x-amz-content-sha256", auth.getDataHash())
                    .header("Authorization", authstr)
                    .build();
            Call call = c.newCall(r);
            //同步调用,返回Response,会抛出IO异常
            Response res = call.execute();
            //System.out.println("返回头：\n"+res.headers().toString());
            return  res.code()==200;

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    }
}
